﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using RestSharp;
using System.IO;
using System.Net.Http;
using System.Net.Http.Headers;
using DidaManager.Log;

namespace DidaManager.Native.Network
{
    public class HttpManager
    {
        // 定义每次上传的块大小（2KB）
        private const int CHUNK_SIZE = 2048;

        public static RestResponse Get(string url,uint Timeout = 3000)
        {
            var client = new RestClient(url);
            var request = new RestRequest();
            request.AddHeader("Content-Type", "application/json");
            request.Timeout = TimeSpan.FromMilliseconds(Timeout);
            return client.Get(request);
        }

        public static RestResponse Get(string url, string token, uint Timeout = 3000)
        {
            var client = new RestClient(url);
            var request = new RestRequest();
            request.AddHeader("Content-Type", "application/json");
            request.AddHeader("token", token);
            request.Timeout = TimeSpan.FromMilliseconds(Timeout);
            return client.Get(request);
        }

        public static RestResponse Post(string url, string data,uint Timeout = 3000)
        {
            var options = new RestClientOptions(url)
            {
                RemoteCertificateValidationCallback = (sender, certificate, chain, sslPolicyErrors) => true
            };
            var client = new RestClient(options);
            var request = new RestRequest();
            request.AddParameter("application/json", data, ParameterType.RequestBody);
            request.Timeout = TimeSpan.FromMilliseconds(Timeout);
            return client.Post(request);
        }

        public static RestResponse Put(string url, string data,uint Timeout = 3000)
        {
            var client = new RestClient(url);
            var request = new RestRequest();
            request.AddParameter("application/json", data, ParameterType.RequestBody);
            request.Timeout = TimeSpan.FromMilliseconds(Timeout);
            return client.Put(request);
        }

        public static RestResponse Delete(string url, string data,uint Timeout = 3000)
        {
            var client = new RestClient(url);
            var request = new RestRequest();
            request.AddParameter("application/json", data, ParameterType.RequestBody);
            request.Timeout = TimeSpan.FromMilliseconds(Timeout);
            return client.Delete(request);
        }

        public static RestResponse Options(string url, string data, string token, uint Timeout = 3000)
        {
            var client = new RestClient(url);
            var request = new RestRequest();
            request.AddParameter("application/json", data, ParameterType.RequestBody);
            request.AddHeader("token", token);
            request.Timeout = TimeSpan.FromMilliseconds(Timeout);
            return client.Options(request);
        }

        /// <summary>
        /// 上传单个数据块
        /// </summary>
        /// <param name="serverUrl">服务器地址</param>
        /// <param name="fileName">文件名称</param>
        /// <param name="offset">当前数据块的偏移量</param>
        /// <param name="data">要发送的数据</param>
        /// <param name="dataSize">数据大小</param>
        /// <param name="isEnd">是否是最后一块数据（1 = 结束, 0 = 继续）</param>
        /// <param name="timeout">超时时间(毫秒)</param>
        /// <returns>成功返回true，失败返回false</returns>
        private static bool UploadChunk(string serverUrl, string fileName, long offset, byte[] data, int dataSize, int isEnd, uint timeout)
        {
            try
            {
                // 构造URL，添加查询参数
                var urlWithParams = $"{serverUrl}?file={Uri.EscapeDataString(fileName)}&offset={offset}&isEND={isEnd}";

                // 创建RestClient选项
                var options = new RestClientOptions(urlWithParams)
                {
                    RemoteCertificateValidationCallback = (sender, certificate, chain, sslPolicyErrors) => true
                };

                var client = new RestClient(options);
                var request = new RestRequest();
                
                // 设置为POST请求
                request.Method = Method.Post;
                
                // 添加Content-Type头
                request.AddHeader("Content-Type", "application/octet-stream");
                
                // 添加二进制数据
                request.AddParameter("application/octet-stream", data.Take(dataSize).ToArray(), ParameterType.RequestBody);
                
                // 设置超时
                request.Timeout = TimeSpan.FromMilliseconds(timeout);

                // 执行请求
                var response = client.Execute(request);
                
                // 检查响应是否成功
                return response.IsSuccessful;
            }
            catch (Exception ex)
            {
                Console.WriteLine($"上传数据块失败: {ex.Message}");
                return false;
            }
        }

        /// <summary>
        /// 模块分块更新
        /// </summary>
        /// <param name="url">更新URL</param>
        /// <param name="filePath">文件路径</param>
        /// <param name="Timeout">超时时间(毫秒)</param>
        /// <returns>HTTP响应</returns>
        public static RestResponse ModuleChunkUpdate(string url, string filePath, uint Timeout = 3000)
        {
            RestResponse finalResponse = new RestResponse();

            try
            {
                // 验证参数
                if (string.IsNullOrEmpty(url))
                {
                    throw new ArgumentException("URL不能为空");
                }

                if (string.IsNullOrEmpty(filePath))
                {
                    throw new ArgumentException("文件路径不能为空");
                }

                // 检查文件是否存在
                if (!File.Exists(filePath))
                {
                    throw new FileNotFoundException($"文件不存在: {filePath}");
                }

                // 获取文件名
                string fileName = Path.GetFileName(filePath);

                // 打开文件进行读取
                using (FileStream fileStream = new FileStream(filePath, FileMode.Open, FileAccess.Read))
                {
                    byte[] buffer = new byte[CHUNK_SIZE];
                    int bytesRead;
                    long offset = 0;
                    bool success = true;

                    // 循环读取文件并分块上传
                    while ((bytesRead = fileStream.Read(buffer, 0, CHUNK_SIZE)) > 0)
                    {
                        // 判断是否是最后一个块
                        int isEnd = (fileStream.Position >= fileStream.Length) ? 1 : 0;

                        LogManager.Info($"上传 {bytesRead} 字节，偏移量 {offset}，isEND={isEnd}...");
                        // 上传当前数据块
                        if (!UploadChunk(url, fileName, offset, buffer, bytesRead, isEnd, Timeout))
                        {
                            LogManager.Error($"上传失败，偏移量: {offset}");
                            success = false;
                            break;
                        }

                        offset += bytesRead;
                    }

                    // 设置最终响应
                    if (success)
                    {
                        finalResponse.StatusCode = System.Net.HttpStatusCode.OK;
                        finalResponse.Content = $"文件上传成功，总共上传 {offset} 字节";
                        LogManager.Info($"文件上传成功，总共上传 {offset} 字节");
                    }
                    else
                    {
                        finalResponse.StatusCode = System.Net.HttpStatusCode.InternalServerError;
                        finalResponse.Content = $"文件上传失败，在偏移量 {offset} 处中断";
                        LogManager.Error($"文件上传失败，在偏移量 {offset} 处中断");
                    }
                }
            }
            catch (Exception ex)
            {
                // 返回错误响应
                finalResponse.StatusCode = System.Net.HttpStatusCode.InternalServerError;
                finalResponse.Content = $"分块上传失败: {ex.Message}";
                LogManager.Error($"分块上传失败: {ex.Message}");
            }

            return finalResponse;
        }

        /// <summary>
        /// 更新文件
        /// </summary>
        /// <param name="url">上传URL</param>
        /// <param name="filePath">文件路径</param>
        /// <param name="updateAreaName">更新区域名字</param>
        /// <param name="timeout">超时时间(毫秒)</param>
        /// <returns>HTTP响应</returns>
        public static RestResponse FileUpload(string url, string filePath, string updateAreaName, uint timeout = 30000)
        {
            try
            {
                // 验证参数
                if (string.IsNullOrEmpty(url))
                {
                    throw new ArgumentException("URL不能为空");
                }

                if (string.IsNullOrEmpty(filePath))
                {
                    throw new ArgumentException("文件路径不能为空");
                }

                if (string.IsNullOrEmpty(updateAreaName))
                {
                    throw new ArgumentException("更新区域名字不能为空");
                }

                // 检查文件是否存在
                if (!File.Exists(filePath))
                {
                    throw new FileNotFoundException($"文件不存在: {filePath}");
                }

                // 创建HttpClient
                using (var httpClient = new HttpClient())
                {
                    // 设置超时时间
                    httpClient.Timeout = TimeSpan.FromMilliseconds(timeout);

                    // 创建multipart/form-data内容
                    using (var multipartContent = new MultipartFormDataContent())
                    {
                        // 读取文件内容
                        var fileBytes = File.ReadAllBytes(filePath);
                        var fileContent = new ByteArrayContent(fileBytes);

                        // 设置文件名
                        string fileName = Path.GetFileName(filePath);
                        fileContent.Headers.ContentDisposition = new ContentDispositionHeaderValue("form-data")
                        {
                            Name = updateAreaName, // 使用更新区域名字作为字段名
                            FileName = fileName
                        };

                        // 添加到multipart内容
                        multipartContent.Add(fileContent);

                        // 发送POST请求
                        var response = httpClient.PostAsync(url, multipartContent).Result;

                        // 创建RestResponse对象
                        var restResponse = new RestResponse();
                        
                        // 设置响应属性
                        restResponse.StatusCode = response.StatusCode;
                        restResponse.Content = response.Content.ReadAsStringAsync().Result;
                        
                        // IsSuccessful是只读属性，由RestResponse内部根据StatusCode自动计算
                        // 不需要手动设置

                        return restResponse;
                    }
                }
            }
            catch (Exception ex)
            {
                // 返回错误响应
                var errorResponse = new RestResponse();
                errorResponse.StatusCode = System.Net.HttpStatusCode.InternalServerError;
                errorResponse.Content = $"更新失败: {ex.Message}";
                
                return errorResponse;
            }
        }

    }
}
